package cn.finedo.service;

import cn.finedo.aiability.AiAbilityV1;
import cn.finedo.common.NonUtil;
import cn.finedo.common.ReturnValueDomain;
import cn.finedo.dto.DynamicRequestRouterDto;
import cn.finedo.dto.ModelCallDto;
import cn.finedo.dto.OpticalSplitDto;
import cn.finedo.entity.AiAbilityEntity;
import cn.finedo.mapper.AiAbilityMapper;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class DynamicRequestRouterService {
    //日志
    private final Logger logger =   LoggerFactory.getLogger(this.getClass());

    @Value("${thirdmodelconfig.opticalsplit}")
    private String opticalspliturl;

    @Autowired
    private AiAbilityMapper aiAbilityMapper;

    public ReturnValueDomain<DynamicRequestRouterDto> dynamicRequestRouter(DynamicRequestRouterDto dto) {
        ReturnValueDomain<DynamicRequestRouterDto> ret = new ReturnValueDomain<>();
        JSONObject jsonObject = JSONObject.parseObject(dto.getRequestMsg());
        String projectId = jsonObject.getString("project");
        if (NonUtil.isNon(projectId)) {
            return ret.setFail("ai编码参数不能为空");
        }
        String requestParam = jsonObject.getString("requestParam");
        ReturnValueDomain<AiAbilityEntity> validInfoResult = queryEntityByAICode(projectId);
        if (validInfoResult == null || validInfoResult.isFail()) {
            return ret.setFail("鉴别ai能力失败");
        }
        AiAbilityEntity entity = validInfoResult.getObject();
        AiAbilityV1 aiAbilityV1 = new AiAbilityV1(entity.getEopAddress(), requestParam);
        aiAbilityV1.setAppId(entity.getAppId());
        aiAbilityV1.setAppKey(entity.getAppKey());
        String result = null;
        try {
            result = aiAbilityV1.callServer();
        } catch (Exception e) {
            logger.error("调用服务失败", e);
            return ret.setFail("调用服务失败");
        }
        if (result == null) {
            return ret.setFail("调用服务失败，返回内容null");
        }
        dto.setResultInfo(result);
        dto.setRequestMsg(null);
        logger.info("result结果: "+ JSONObject.toJSONString(dto));
        return ret.setSuccess("服务调用成功", dto);
    }

    public ReturnValueDomain<AiAbilityEntity> queryEntityByAICode(String projectId) {
        ReturnValueDomain<AiAbilityEntity> ret = new ReturnValueDomain<>();
        LambdaQueryWrapper<AiAbilityEntity> qw = new LambdaQueryWrapper<>();
        qw.eq(AiAbilityEntity::getAiCode, projectId);
        AiAbilityEntity entity = null;
        try {
            entity = aiAbilityMapper.selectOne(qw);
        } catch (Exception e) {
            logger.error("鉴别ai能力目录失败，错误信息", e);
            return ret.setFail("鉴别ai能力目录失败");
        }
        return ret.setSuccess("鉴别成功", entity);
    }

    /**
     * 调用模型服务，返回上传的文件标注情况
     * @param modelCallDto
     * @return
     */
    public ReturnValueDomain<ModelCallDto> modelServiceCall(ModelCallDto modelCallDto) {
        ReturnValueDomain<ModelCallDto> ret = new ReturnValueDomain<>();
        //参数验证
        if (isInvalidProject(modelCallDto)) {
            return ret.setFail("缺少必要参数project:[模型服务编码]");
        }

        // 数据库查询
        AiAbilityEntity entity = findAiAbilityEntity(modelCallDto.getAiNo());
        if (entity == null) {
            return ret.setFail("模型服务不存在");
        }

        // 设置模型调用参数并调用模型
        modelCallDto.setUrlStr(entity.getIpAddress());
        modelCallDto.setYoloModelPath(entity.getModelroute());
        return modelCall(modelCallDto);
    }

    private boolean isInvalidProject(ModelCallDto modelCallDto) {
        JSONArray array = JSONObject.parseArray(modelCallDto.getProject());
        if (array == null || array.size() == 0) {
            return true;
        }
        modelCallDto.setAiNo(array.getString(0));
        return Objects.isNull(modelCallDto.getAiNo()) || modelCallDto.getAiNo().isEmpty();
    }

    private AiAbilityEntity findAiAbilityEntity(String aiNo) {
        LambdaQueryWrapper<AiAbilityEntity> qw = new LambdaQueryWrapper<>();
        qw.eq(AiAbilityEntity::getAiCode, aiNo);
        try {
            return aiAbilityMapper.selectOne(qw);
        } catch (Exception e) {
            logger.error("查询对应的模型服务失败", e);
            throw new RuntimeException("查询对应的模型服务失败");
        }
    }

    public ReturnValueDomain<ModelCallDto> modelCall(ModelCallDto modelCallDto) {
        ReturnValueDomain<ModelCallDto> ret = new ReturnValueDomain<>();
        JSONObject requestJson = createRequestJson(modelCallDto);
        logger.info("请求参数:" + requestJson.toJSONString());
        logger.info("调用地址:" + modelCallDto.getUrlStr());
        HttpURLConnection conn = null;
        try {
            URL url = new URL(modelCallDto.getUrlStr());
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setConnectTimeout(30000);
            conn.setReadTimeout(10000);
            conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
            conn.setRequestProperty("Accept", "application/json");

            try (OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8")) {
                out.write(requestJson.toJSONString());
            }

            int code = conn.getResponseCode();
            if (200 == code) {
                try (BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"))) {
                    StringBuilder result = new StringBuilder();
                    String line;
                    while ((line = in.readLine()) != null) {
                        result.append(line);
                    }
                    JSONObject obj = handlerResult(result.toString()); // 注意这里可能抛出异常，需要处理
                    ModelCallDto returnDto = new ModelCallDto();
                    returnDto.setHandleResult(obj);
                    return ret.setSuccess("处理成功", returnDto);
                }
            } else {
                return ret.setFail("连接失败");
            }
        } catch (Exception e) {
            logger.error("调用模型服务失败", e);
            return ret.setFail("调用模型服务失败");
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }
    }

    private JSONObject createRequestJson(ModelCallDto modelCallDto) {
        JSONObject requestJson = new JSONObject();
        List<String> projectList = new ArrayList<>();
        projectList.add(modelCallDto.getYoloModelPath());
        requestJson.put("detectimg", modelCallDto.getDetectimg());
        requestJson.put("project", projectList);
        return requestJson;
    }

    public JSONObject handlerResult(String jsonString) {
        if (null == jsonString || jsonString.isEmpty()) {
            return null;
        }
        try {
            JSONObject jsonObject = JSONObject.parseObject(jsonString);
            //获取code与message
            JSONObject resultObject = new JSONObject();
            // 获取code与message
            String code = jsonObject.getString("code");
            String message = jsonObject.getString("message");
            resultObject.put("code", code);
            resultObject.put("message", message);
            resultObject.put("result", new HashMap<>());
            //解析data
            JSONObject dataObject = jsonObject.getJSONObject("data");
            if (dataObject != null) {
                Iterator<String> keys = dataObject.keySet().iterator();
                if (keys.hasNext()) {
                    String key = keys.next();
                    JSONObject fileDataObject = dataObject.getJSONObject(key);
                    JSONArray cordArray = fileDataObject.getJSONArray("cord");
                    // 分组计数
                    if (cordArray != null) {
                        List<JSONArray> cordList = cordArray.toJavaList(JSONArray.class);
                        Map<String, Long> groupedItems = cordList.stream()
                                .map(item -> item.getString(6))
                                .collect(Collectors.groupingBy(itemName -> itemName, Collectors.counting()));

                        // 处理结果,覆盖上面的result值
                        resultObject.put("result", groupedItems);
                    }
                }
            }
            return resultObject;
        } catch (Exception e) {
            logger.error("处理返回数据异常", e);
            return null;
        }
    }

    /**
     * 调用分光器端口检测服务
     * @param dto
     * @return
     */
    public JSONObject OpticalSplit(OpticalSplitDto dto) {
        try {
            byte[] imgeBase64 = Base64.getDecoder().decode(dto.getImageBase64());
            String fileName = dto.getFileName();
            // 发送表单数据
            try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
                HttpPost postRequest = createPostRequest(opticalspliturl, imgeBase64, fileName);
                try (CloseableHttpResponse response = httpClient.execute(postRequest)) {
                    HttpEntity responseEntity = response.getEntity();
                    if (responseEntity != null) {
                        String responseString = EntityUtils.toString(responseEntity);
                        return JSONObject.parseObject(responseString);
                    } else {
                        logger.error("Received null response entity");
                        return createErrorJson("No response from server");
                    }
                }
            }
        } catch (IllegalArgumentException e) {
            logger.error("Invalid Base64 string", e);
            return createErrorJson("Invalid Base64 content");
        } catch (IOException e) {
            logger.error("调用模型服务失败", e);
            return createErrorJson("Failed to call API");
        } catch (Exception e) {
            logger.error("Unexpected error", e);
            return createErrorJson("Unexpected error");
        }
    }

    /**
     * 创建请全体
     * @param url
     * @param imageData
     * @param fileName
     * @return
     */
    private HttpPost createPostRequest(String url, byte[] imageData, String fileName) {
        HttpPost postRequest = new HttpPost(url);
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        builder.addBinaryBody("files", new ByteArrayInputStream(imageData), ContentType.APPLICATION_OCTET_STREAM, fileName);
        HttpEntity multiPart = builder.build();
        postRequest.setEntity(multiPart);
        return postRequest;
    }

    /**
     * 错误返回信息
     * @param errorMessage
     * @return
     */
    public JSONObject createErrorJson(String errorMessage) {
        JSONObject requestJson = new JSONObject();
        requestJson.put("error", errorMessage);
        return requestJson;
    }
}
